<!--
 * @Author: DingNanLin 1981261270@qq.com
 * @Date: 2024-12-02 14:47:06
 * @LastEditors: DingNanLin 1981261270@qq.com
 * @LastEditTime: 2024-12-16 15:03:57
 * @FilePath: \water-soil-conservation-web\src\views\liveMonitor\index.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<!-- 实况监测 -->
<template>
    <div class="live-monitor">
        <div class="left-container" v-if="mapLoadSuccess">
            <div class="card-container animate__animated animate__backInLeft">
                <div class="card-title">站点总览</div>
                <div class="card-content">
                    <template v-if="mapAreaDataList && mapAreaDataList.length > 0">
                        <div
                            class="card-item"
                            v-for="(item, index) in mapAreaDataList"
                            :key="index"
                            @click="handelClickItem(item)"
                            :class="activeDamItem.id === item.id ? 'active' : ''"
                        >
                            <el-icon><Menu /></el-icon>
                            <div class="name">
                                {{ item.areaName }}
                            </div>
                        </div>
                    </template>
                    <div class="no-data" v-else>暂无数据</div>
                </div>
            </div>
        </div>
        <div class="right-container" v-if="mapLoadSuccess">
            <div class="pane-container">
                <!-- 总览面板 -->
                <div class="pane overview-pane show">
                    <!-- 站点介绍 -->
                    <div class="site-intro card-container">
                        <div class="card-title">站点介绍</div>
                        <div class="card-content">
                            <div class="info">
                                <div class="info-list">
                                    <div class="item">
                                        <span class="label"> 名称： </span>
                                        <span class="value">
                                            {{ activeDamItem.areaName }}
                                        </span>
                                    </div>
                                    <div class="item">
                                        <span class="label"> 编码： </span>
                                        <span class="value">
                                            {{ activeDamItem.projectCode }}
                                        </span>
                                    </div>
                                    <div class="item">
                                        <span class="label"> 地址： </span>
                                        <span class="value">
                                            {{ activeDamItem.projectAddress }}
                                        </span>
                                    </div>
                                    <div class="item">
                                        <span class="label"> 面积： </span>
                                        <span class="value"> {{ activeDamItem.projectAreaSize }} km² </span>
                                    </div>
                                    <div class="item">
                                        <span class="label"> 负责人： </span>
                                        <span class="value">
                                            {{ activeDamItem.contactPerson }}
                                        </span>
                                    </div>
                                    <div class="item">
                                        <span class="label"> 联系方式： </span>
                                        <span class="value">
                                            {{ activeDamItem.contactPhone }}
                                        </span>
                                    </div>
                                </div>
                                <div class="info-text">
                                    <div class="main">
                                        {{ activeDamItem.areaDesc }}
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
					<!-- 实况数据面板 -->
					<transition
						enter-active-class="animate__animated animate__bounceIn"
						leave-active-class="animate__animated animate__bounceOut"
					>
						<div class="device-data-pane card-container" v-if="showDeviceDataPane">
							<div class="card-title">
								<div>实况数据</div>
								<div class="icon" @click="handelViewDeviceDataDialog">
									<el-icon><Menu /></el-icon>
								</div>
							</div>
							<div class="card-content">
								<!-- 摄像头数据 -->
								<div class="video-data" v-if="activeDeviceType.code == 8">
									<vue3videoPlay
										ref="rightVideoPlay"
                                        width="100%"
                                        height="100%"
                                        :title="deviceVideoData.sbmc"
                                        :src="deviceVideoData.deviceUrl"
										v-bind="options"
                                    />
								</div>
								<!-- 其他数据 -->
								<div class="device-data" v-else>
									<template  v-for="(item, index) in deviceDataTableHeader" :key="index">
										<div class="item" v-if="item.column_name !== 'flag'">											
											<div class="label">
												{{ item.description}}
											</div>
											<div class="value" >
												{{ deviceDataNowList?.[item.column_name]}}
											</div>											
										</div>
									</template>
								</div>
							</div>
						</div>
					</transition>
                </div>
            </div>
        </div>
        <transition>
            <div class="center-container animate__animated animate__backInUp" v-if="loadData">
                <div
                    class="item"
                    v-for="(item, index) in deviceTypeList"
                    :key="index"
                    @click="handelDeviceClick(item)"
                    :class="activeDeviceType.id === item.id ? 'active' : ''"
                >
                    <div class="icon">
                        <img :src="item.logo" alt="" />
                    </div>
                    <div class="name">
                        {{ item.name }}
                    </div>
                </div>
            </div>
        </transition>
        <div class="map-box">
            <map-3d
                :mapId="mapConfig.mapId"
                :center="mapConfig.center"
                :terrain="mapConfig.terrain"
                :basemaps="mapConfig.basemaps"
                @MapLoadSuccess="handelMapLoadSuccess"
            />
        </div>
        <transition>
			<div class="dialog-container" v-if="showDeviceDataDialog">
                <div class="dialog-title">
                    <div class="name">数据详情</div>
                    <div class="close" @click="showDeviceDataDialog = false">
                        <el-icon><CircleClose /></el-icon>
                    </div>
                </div>
                <div class="dialog-main" v-if="showDeviceDataDialog">
					<div class="video-container" v-if="activeDeviceType.code == 8">
						<vue3videoPlay
							ref="dialogVideoPlay"
							width="100%"
							height="100%"
							:title="deviceVideoData.sbmc"
							:src="deviceVideoData.deviceUrl"
							v-bind="options"
						/>
					</div>
					<div class="table-container" v-else>
						<div class="table-main">
							<base-table
								:tableData="deviceDataList"
								:tableHeader="deviceDataTableHeader"
								:tableHeight="'100%'"
							/>
						</div>
						<div class="pagination-main">
							<el-pagination background layout="prev, pager, next" :total="totalCount" @current-change="handelPageChange"/>
						</div>
					</div>
                </div>
            </div>
        </transition>
    </div>
</template>
<script setup>
import Map3d from '@/components/map3d/index'
import { ref, inject, nextTick } from 'vue'
import { loadImg } from '@/utils/loadImg.js'
import { areaList, deviceType, deviceList, deviceData } from '@/http/apis/index.js'
import vue3videoPlay from 'vue3-video-play' // 引入组件
import 'vue3-video-play/dist/style.css' // 引入css
import BaseTable from '@/components/baseTable/baseTable.vue'
// 右侧视频播放器
const rightVideoPlay = ref(null)
const mars3d = inject('mars3d')
const Cesium = inject('Cesium')
// 地图是否加载成功
let mapLoadSuccess = ref(false)
// 加载数据
let loadData = ref(false)
// 地图对象
let map = null
// 数据图层组
let mapLayerGroup = null
// gis地址
const GIS_API = import.meta.env.VITE_API_GIS_API
// 地图配置
const mapConfig = {
    mapId: 'liveMonitorMap',
    center: { lat: 35.823295, lng: 109.210225, alt: 3129.4, heading: 5.7, pitch: -31.3 },
    terrain: {
        url: '//data.mars3d.cn/terrain',
        show: true
    },
    basemaps: [
        {
            name: '高德影像',
            pid: 10,
            type: 'group',
            show: true,
            layers: [
                {
                    name: '高德影像',
                    type: 'gaode',
                    layer: 'img_d'
                },
                {
                    name: '高德影像',
                    type: 'gaode',
                    layer: 'img_z'
                }
            ]
        }
    ]
}
// 淤地坝列表数据
const mapAreaDataList = ref([])
// 选中的淤地坝数据
const activeDamItem = ref({})
// 设备类型列表
const deviceTypeList = ref([])
// 选中的设备类型
const activeDeviceType = ref({})
// 选中设备类型下的设备列表
const deviceListData = ref([])
// 右侧设备数据面板是否显示
const showDeviceDataPane = ref(false)
// 右侧数据表格弹框是否展示
const showDeviceDataDialog = ref(false)
// 查询右侧设备数据列表参数
const deviceDataParams = ref({
    deviceId: '',
    deviceType: '',
	pageSize: 10,
	pageNo:1
})
// 设备列表数据总条数
const totalCount = ref(0)
// 右侧设备数据面板数据
const deviceDataList = ref([]);
// 右侧设备数据面板实况数据
const deviceDataNowList = ref({});
// 右侧设备数据面板表头数据
const deviceDataTableHeader = ref([]);
// 右侧面板摄像头类型数据
const deviceVideoData = ref({});
// 视频播放器配置项
const options = {
	mirror: false, //镜像画面
	controlBtns: [
		"audioTrack",
		"quality",
		"volume",
	], //显示所有按钮,
}
/**
 * 地图加载完成
 */
const handelMapLoadSuccess = res => {
    map = res
    mapLoadSuccess.value = true
    // 创建数据图层组
    createMapLayerGroup()
    // 获取地图区域数据
    handelFeatchMapAreaData()
}
/**
 * 创建地图数据图层组
 */
const createMapLayerGroup = () => {
    mapLayerGroup = new mars3d.layer.GroupLayer({
        id: 'live-monitor-point-layer',
        name: '实况监测数据图层组',
        flyTo: true
    })
    map.addLayer(mapLayerGroup)
}
/**
 * 获取项目列表
 */
const handelFeatchMapAreaData = async () => {
    let res = await areaList({})
    if (res && res.code === 0) {
        mapAreaDataList.value = res.data
        //默认选中淤地坝
        handelClickItem(mapAreaDataList.value[0])
    } else {
        mapAreaDataList.value = []
    }
}

/**
 * 项目列表点击
 */
const handelClickItem = item => {
	activeDamItem.value = { ...item };
	loadData.value = true;
	showDeviceDataPane.value = false;
    addMapAreaData(item)
	handelFeatchDeviceType();
	deviceDataParams.value.pageNo = 1;
	// addModelData();
}
/**
 * 叠加项目列表
 */
const addMapAreaData = item => {
    mapLayerGroup.eachLayer(layer => {
        if (layer.id === 'area-layer') {
            mapLayerGroup.removeLayer(layer, true)
        }
    })
    const geoJsonLayer = new mars3d.layer.GeoJsonLayer({
        name: '范围数据',
        id: 'area-layer',
        data: item.areaJson,
        attr: item,
		flyTo: true,
		flyToOptions: {
			scale: 8,
			pitch:-89
		}
    })
    mapLayerGroup.addLayer(geoJsonLayer)
}


/**
 * 查询项目关联的设备类型
 */
const handelFeatchDeviceType = async () => {
	let res = await deviceType({
		areaId: activeDamItem.value.id
	})
	if (res && res.code === 0) {
		deviceTypeList.value = res.data;
		handelAddDevicePoint()
	} else { 
		deviceTypeList.value = [];
	}
}


/**
 * 添加模型数据
 */
const addModelData = () => {
    mapLayerGroup.eachLayer(layer => {
        if (layer.id === 'model-layer') {
            mapLayerGroup.removeLayer(layer, true)
        }
	})
	let tileLayer1 = new mars3d.layer.WmtsLayer({
		id: 'model-layer',
		url: GIS_API + '/geoserver/Ele_Map/gwc/service/wmts',
		layer: 'Ele_Map:fuxianchang_transparent_mosaic_grou',
		format: 'image/png',
		tileMatrixSetID: 'EPSG:4326',
		crs: 'EPSG:4326'
	})
	let tileLayer2 = new mars3d.layer.TilesetLayer({
		name: '县城社区',
		url: '/model/tileset.json',
		maximumScreenSpaceError: 1,
		maxMemory: 2048, // 最大缓存内存大小(MB)
		cullWithChildrenBounds: false,
		skipLevelOfDetail: true,
		preferLeaves: true,
		enableDebugWireframe: true, // 是否可以进行三角网的切换显示
	})
	mapLayerGroup.addLayer(tileLayer1);
	mapLayerGroup.addLayer(tileLayer2)
}

/**
 * 项目关联的设备类型点击
 */
const handelDeviceClick = async item => {
    removeDevicePoint()
    if (activeDeviceType.value?.id === item.id) {
        activeDeviceType.value = {}
    } else {
        activeDeviceType.value = { ...item }
		await nextTick()
		console.log('item-----', item)
		deviceDataParams.value.pageNo = 1;
		showDeviceDataPane.value = false;
		handelFeatchDeviceList(item.code)
    }
}
/**
 * 查询设备类型下的设备点位列表
 */
const handelFeatchDeviceList = async (typeId) => {
    let res = await deviceList({
		areaId: activeDamItem.value.id,
		devType:typeId,
	})
    if (res && res.code === 0) {
		deviceListData.value = res.data;
		removeDevicePoint();
		handelAddDevicePoint()
    } else {
        deviceListData.value = []
    }
}
/**
 * 添加设备类型下的设备点位
 */
const handelAddDevicePoint = () => {
    const graphicLayer = new mars3d.layer.GraphicLayer({
        name: '站点数据',
        id: 'device-list-layer'
    })
    mapLayerGroup.addLayer(graphicLayer)
	deviceListData.value.forEach(item => {
        const graphic = new mars3d.graphic.BillboardEntity({
            position: [item.lon, item.lat],
            style: {
                image: loadImg('icon-point.png'),
                width: 30,
                height: 80,
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                clampToGround: true
            },
            attr: item
        })
        graphicLayer.addGraphic(graphic)
		graphic.on(mars3d.EventType.click, function (event) {
			showDeviceDataPane.value = false;
			if (activeDeviceType.value.code == 8) { 
				showDeviceDataPane.value = true;
				deviceVideoData.value = item;
			} else {
				handelFeatchDeviceData(event.graphic.attr);
			}
        })
    })
}
/**
 * 移除设备点位
 */
const removeDevicePoint = () => {
    mapLayerGroup.eachLayer(layers => {
        if (layers.options && layers.options.id === 'device-list-layer') {
            mapLayerGroup.removeLayer(layers)
        }
    })
}
/**
 * 查询设备点位的详情数据
 */
const handelFeatchDeviceData = async (item) => { 
	if (item) { 
		deviceDataParams.value.deviceId = item.id;
	} 
	deviceDataParams.value.deviceType = activeDeviceType.value.code;
	let res = await deviceData(deviceDataParams.value)
	if (res && res.code === 0) {
		showDeviceDataPane.value = true;
		deviceDataList.value = res.data.data.list;
		console.log('res.data.data', res.data.data)
		totalCount.value = res.data.data.totalCount
		deviceDataTableHeader.value = res.data.tableInfo;
		deviceDataTableHeader.value.forEach(ele => { 
			ele.columnLabel = ele.description;
			ele.columnProp = ele.column_name;
			ele.columnWidth='200'
		})
		if (deviceDataParams.value.pageNo == 1) { 
			deviceDataNowList.value = deviceDataList.value[0]
		}
	} else {
		deviceDataList.value = [];
		deviceDataTableHeader.value = [];
	}
}
/**
 * 查看设备详情数据
 */
const handelViewDeviceDataDialog = () => { 
	if (activeDeviceType.value.code == 8) { 
		showDeviceDataDialog.value = true;
		rightVideoPlay.value.pause()
	} else {
		showDeviceDataDialog.value = true;
	}
	console.log('deviceDataTableHeader.value', deviceDataTableHeader.value);
	console.log('deviceDataList.value', deviceDataList.value)
}
/**
 * 设备数据页码改变
 */
const handelPageChange = (e) => { 
	deviceDataParams.value.pageNo = e;
	handelFeatchDeviceData();
}
</script>
<style lang="scss" scoped>
.live-monitor {
    @include box-flex($width: 100%, $height: 100%, $direction: column, $justify: center, $align: center);
	position: relative;
    .map-box {
        @include box-flex($width: 100%, $height: 100%, $direction: column, $justify: center, $align: center);
    }
    .left-container {
        position: absolute;
        left: 10px;
        top: 80px;
        @include box-flex(
            $width: 350px,
            $height: calc(100% - 100px),
            $direction: column,
            $justify: space-between,
            $align: center
        );
        z-index: 1000;
        > .card-container {
            @include box-flex($width: 100%, $height: 100%, $direction: column, $justify: center, $align: center);
            .card-content {
                @include box-flex(
                    $width: 100%,
                    $height: auto,
                    $direction: column,
                    $justify: flex-start,
                    $align: center,
                    $flex-1: 1
                );
                overflow-y: auto;
                padding: 20px;
                .card-item {
                    @include box-flex(
                        $width: 100%,
                        $height: 40px,
                        $direction: row,
                        $justify: flex-start,
                        $align: center
                    );
                    background: url('@/views/liveMonitor/images/bg-menu.png') no-repeat;
                    background-size: 100% 100%;
                    margin-bottom: 20px;
                    padding: 0 20px;
                    transition: all 0.3s;
                    cursor: pointer;
                    .name {
                        margin-left: 10px;
                        cursor: pointer;
                    }
                    &:hover {
                        background: url('@/views/liveMonitor/images/bg-menu-d.png') no-repeat;
                        background-size: 100% 100%;
                    }
                }
                .card-item.active {
                    background: url('@/views/liveMonitor/images/bg-menu-d.png') no-repeat;
                    background-size: 100% 100%;
                }
                .no-data {
                    @include box-flex(
                        $width: 100%,
                        $height: 100%,
                        $direction: column,
                        $justify: center,
                        $align: center
                    );
                }
            }
        }
    }
    .right-container {
        position: absolute;
        right: 10px;
        top: 80px;
		overflow: hidden;
        @include box-flex(
            $width: 350px,
            $height: calc(100% - 100px),
            $direction: column,
            $justify: space-between,
            $align: center
        );
        z-index: 1000;
        .pane-container {
            @include box-flex($width: 100%, $height: 100%, $direction: column, $justify: center, $align: center);
			overflow: hidden;
            .pane {
                @include box-flex(
                    $width: 100%,
                    $height: 100%,
                    $direction: column,
                    $justify: flex-start,
                    $align: center
                );
                transition: all 0.3s;
                > .card-container {
                    @include box-flex(
                        $width: 100%,
                        $height: auto,
                        $direction: column,
                        $justify: center,
                        $align: center
                    );
                    margin-bottom: 10px;
                    .card-content {
                        @include box-flex(
                            $width: 100%,
                            $height: auto,
                            $direction: column,
                            $justify: center,
                            $align: center,
                            $flex-1: 1
                        );
                        .chart-main {
                            @include box-flex(
                                $width: 100%,
                                $height: 100%,
                                $direction: column,
                                $justify: center,
                                $align: center
                            );
                            > div {
                                width: 100% !important;
                                height: 100% !important;
                            }
                        }
                    }
                }
                .site-intro {
                    @include box-flex($width: 100%, $height: auto, $direction: column, $justify: center, $align: center,$flex-1:1);
                    .card-content {
                        padding: 10px;
                        .info {
                            @include box-flex(
                                $width: 100%,
                                $height: 100%,
                                $direction: column,
                                $justify: center,
                                $align: center
                            );
                            .info-list {
                                @include box-flex(
                                    $width: 100%,
                                    $height: auto,
                                    $direction: column,
                                    $justify: flex-start,
                                    $align: center
                                );
                                .item {
                                    @include box-flex(
                                        $width: 100%,
                                        $height: 30px,
                                        $direction: row,
                                        $justify: space-between,
                                        $align: center
                                    );
                                    background: rgba($color: #08223e, $alpha: 0.5);
                                    margin: 5px 0;
                                    padding: 0 20px;
                                }
                            }
                            .info-text {
                                @include box-flex(
                                    $width: 100%,
                                    $height: auto,
                                    $direction: column,
                                    $justify: flex-start,
                                    $align: flex-start,
                                    $flex-1: 1
                                );
                                padding: 10px;
                                .main {
                                    @include box-flex(
                                        $width: 100%,
                                        $height: 100%,
                                        $direction: column,
                                        $justify: flex-start,
                                        $align: flex-start
                                    );
                                    overflow-y: auto;
                                    letter-spacing: 1px;
                                    line-height: 25px;
                                    text-indent: 2em;
                                }
                            }
                        }
                    }
                }
                .device-data-pane {
					@include box-flex($width: 100%, $height: auto, $direction: column, $justify: center, $align: center);
					max-height: 50%;
                    .card-content {
                        @include box-flex(
                            $width: 100%,
                            $height: 100%,
                            $direction: column,
                            $justify: flex-start,
                            $align: center,
                            $flex-1: 1
                        );
                        padding: 10px;
						overflow: hidden;
						.device-data{
							@include box-flex(
								$width: 100%,
								$height: 100%,
								$direction: column,
								$justify: flex-start,
								$align: center
							);
							overflow-y: auto;
							.item{
								@include box-flex(
									$width: 100%,
									$height: auto,
									$direction: row,
									$justify: flex-start,
									$align: center
								);
								margin: 5px 0;
								.label{
									@include box-flex(
										$width: 30%,
										$height: 100%,
										$direction: row,
										$justify: flex-start,
										$align: center
									);
									background: #0f2b3f;
									padding: 10px;
								}
								.value{
									@include box-flex(
										$width: 70%,
										$height: 100%,
										$direction: row,
										$justify: flex-start,
										$align: center
									);
									padding-left:10px;
									background: rgba($color: #08223e, $alpha: 0.5);
								}
							}
						}
                    }
                }
            }
        }
    }
    .center-container {
        position: absolute;
        bottom: 60px;
        @include box-flex($width: auto, $height: auto, $direction: row, $justify: space-between, $align: center);
        z-index: 1000;
        .item {
            @include box-flex($width: 120px, $height: 100px, $direction: column, $justify: center, $align: center);
            background: url('@/views/liveMonitor/images/bg-device-menu.png') no-repeat;
            background-size: 100% 100%;
            padding: 10px 10px 0 0;
            cursor: pointer;
            transition: all 0.3s;
            .icon {
                @include box-flex($width: 30px, $height: 30px, $direction: column, $justify: center, $align: center);
                img {
                    width: 100%;
                    height: auto;
                }
            }
            .name {
                margin-top: 5px;
                font-size: 16px;
                padding-top: 10px;
            }
        }
        .item.active {
            background: url('@/views/liveMonitor/images/bg-device-menu-d.png') no-repeat;
            background-size: 100% 100%;
        }
    }
	.dialog-container {
        @include box-flex($width: 60vw, $height: auto, $direction: column, $justify: center, $align: center);
        position: absolute;
        z-index: 1000;
        background: url('@/views/dataOverview/images/bg-dialog.png') no-repeat;
        background-size: 100% 100%;
        padding: 20px 20px 0 20px;
        .dialog-title {
            @include box-flex($width: 100%, $height: 40px, $direction: row, $justify: space-between, $align: center);
            padding: 0 20px;
            background: #0f2b3f;
            .close {
                cursor: pointer;
                font-size: 20px;
            }
        }
        .dialog-main {
            @include box-flex(
                $width: 100%,
                $height: calc(100% - 40px),
                $direction: row,
                $justify: center,
                $align: center
            );
			.video-container{
				@include box-flex(
					$width: 100%,
					$height: 60vh,
					$direction: column,
					$justify: center,
					$align: center
				);
				padding: 20px 0;
			}
			.table-container{
				@include box-flex(
					$width: 100%,
					$height: 60vh,
					$direction: column,
					$justify: center,
					$align: center
				);
				.table-main{
					@include box-flex(
						$width: 100%,
						$height:auto,
						$direction: column,
						$justify: center,
						$align: center,
						$flex-1:1
					);
					overflow: hidden;
					margin-top: 20px;
				}
				.pagination-main{
					@include box-flex(
						$width: 100%,
						$height: auto,
						$direction: row,
						$justify: flex-end,
						$align: center
					);
					padding: 20px 0;
				}
			}
        }
    }
}
</style>
<style lang="scss">
.scroll {
    @include box-flex($width: 100%, $height: auto, $direction: column, $justify: flex-start, $align: center);
    > div {
        width: 100% !important;
    }
}
</style>
